package com.prig.base.controller;

import cn.hutool.captcha.ShearCaptcha;
import com.prig.base.DTO.input.AdminAccountDto;
import com.prig.base.DTO.input.AdminDto;
import com.prig.base.DTO.input.ChangePasswordDto;
import com.prig.base.DTO.input.PageKeywordSortDto;
import com.prig.base.entity.Admin;
import com.prig.base.service.AdminService;
import com.prig.base.util.response.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequestMapping(path = "/admin")
@Api(value = "管理员")
public class AdminController {


    private AdminService adminService;

    @Autowired
    public void setAdminService(AdminService adminService) {
        this.adminService = adminService;
    }
    @RequestMapping(path = "/register",method = RequestMethod.POST)
    @ApiOperation(value = "注册",notes = "注册接口")
    public Result register( @RequestBody @Valid AdminDto adminDto){
        Admin admin,reqAdmin;
        reqAdmin = new Admin(adminDto.getAccount());
        admin = adminService.getAdmin(reqAdmin);
        if (admin != null){
            return new Result().c400("已存在");
        }
        reqAdmin.setPassword(adminDto.getPassword());
        adminService.saveAdmin(reqAdmin);
        return new Result<>();
    }
    @RequestMapping(path = "/login",method = RequestMethod.POST)
    @ApiOperation(value = "登陆",notes = "登陆接口")
    public Result login(@RequestBody @Valid AdminDto adminDto){
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        //登陆失败次数
        int loginErrorNum = session.getAttribute("loginErrorNum") == null ? 0 : Integer.parseInt(session.getAttribute("loginErrorNum").toString());
        //验证码状态
        boolean captchaStatus = session.getAttribute("captchaStatus") == null ? false : (Boolean) session.getAttribute("captchaStatus");
        if (captchaStatus){
            ShearCaptcha captcha = null;
            if (session.getAttribute("captcha") != null)
                captcha = (ShearCaptcha) session.getAttribute("captcha");
           if (captcha == null || !captcha.verify(adminDto.getCaptchaCode())){

               return errorLogin(session, loginErrorNum,"验证码错误");
           }
        }

        UsernamePasswordToken token = new UsernamePasswordToken(adminDto.getAccount(),adminDto.getPassword());
        try{
            subject.login(token);
        }catch (UnknownAccountException e) {
            return errorLogin(session, loginErrorNum,"不存在账号");
        } catch (IncorrectCredentialsException e) {
            return errorLogin(session, loginErrorNum,"账号密码错误");
        }
        session.setAttribute("loginErrorNum",0);
        session.setAttribute("captchaStatus",false);
        session.setAttribute("user",adminService.getAdmin(new Admin(adminDto.getAccount())));
        return new Result<>();
    }

    /**
     * 登陆失败
     * @param session 会话
     * @param loginErrorNum 登陆错误次数
     * @param msg 信息
     * @return Result
     */
    private Result errorLogin(Session session, int loginErrorNum,String msg) {
        session.removeAttribute("captcha");
        addLoginErrorNum(loginErrorNum,session);
        return new Result<>().c400(msg);
    }

    /**
     * 添加错误登陆次数
     * @param loginErrorNum 登陆错误次数
     * @param session 会话
     */
    private void addLoginErrorNum(int loginErrorNum , Session session){
        int CAPTCHA_OPEN_NUM = 3 ;
        ++loginErrorNum;
        if (loginErrorNum > CAPTCHA_OPEN_NUM ){
            session.setAttribute("captchaStatus",true);
            return;
        }
        session.setAttribute("loginErrorNum",loginErrorNum);
    }

    @RequestMapping(path = "/logout",method = RequestMethod.GET)
    @ApiOperation(value = "登出",notes = "登出接口")
    public Result<String> logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return new Result<>();
    }
    @RequestMapping(path = "/changePassword",method = RequestMethod.POST)
    @ApiOperation(value = "修改密码",notes = "修改密码接口")
    @RequiresPermissions("admin:password")
    public Result changePassword(@RequestBody @Valid ChangePasswordDto dto){
        Admin admin = adminService.getAdmin(new Admin(dto.getAccount(),dto.getPassword()));
        if (admin == null){
            return new Result().c400("账号密码错误");
        }
        admin.setPassword(dto.getChangePassword());
        adminService.saveAdmin(admin,true);
        return new Result("修改成功!!");
    }
    @RequestMapping(path = "/getAdminList",method = RequestMethod.GET)
    @ApiOperation(value = "获取admin列表",notes = "获取admin列表接口")
    @RequiresPermissions("admin:get")
    public Result getAdminList(
                                            PageKeywordSortDto pageKeywordSortDto
    ){
        Page list =adminService.getAdmin(pageKeywordSortDto);
        return new Result<>(list.getContent(),list.getTotalElements());
    }
    @RequestMapping(path = "/noPermission",method = RequestMethod.GET)
    public Result noPermission(){
        return new Result().c400("权限不足");
    }

    @RequestMapping(path = "/delete",method = RequestMethod.POST)
    @ApiOperation(value = "删除管理员",notes = "删除管理员接口")
    @RequiresPermissions("admin:delete")
    public Result delete(@RequestBody String adminIds){
        adminIds = adminIds.replaceAll("\"","");
        adminService.del(adminIds);
        return new Result("删除成功!!");
    }

    @GetMapping(path = "/{id}")
    @ApiOperation(value = "获取管理员",notes = "获取管理员接口")
    @RequiresPermissions("admin:get")
    public Result getAdmin(@PathVariable(name="id") long id){
        Admin admin = adminService.getAdmin(new Admin(id));
        admin.setPassword("");
        if (admin.getAccount() != null){
            return new Result<>(admin);
        }
        return new Result().c400("没有数据");
    }
    @GetMapping(path = "/account")
    public Result getAdminAccount(){
        Admin admin =  (Admin)SecurityUtils.getSubject().getSession().getAttribute("user");
        admin.setPassword("");
        if (admin.getAccount() != null){
            return new Result<>(admin);
        }
        return new Result().c400("没有数据");
    }
    @PutMapping(path = "/{id}")
    @ApiOperation(value = "修改账号",notes = "修改账号接口")
    @RequiresPermissions("admin:account")
    public Result updateAdminAccount(@PathVariable(name = "id")long id,@RequestBody  AdminAccountDto account){

        Admin admin = adminService.getAdmin(new Admin(account.getAccount()));
        if (admin != null){
            return new Result().c400("已存在");
        }
        admin = adminService.getAdmin(new Admin(id));
        admin.setAccount(account.getAccount());
        admin = adminService.saveAdmin(admin);
        return new Result<>(admin);
    }
}
